package cc.rengu.igas.channel.alipay.core.service.trans;

import cc.rengu.igas.channel.alipay.common.constant.*;
import cc.rengu.igas.channel.alipay.common.enums.RespCodeEnum;
import cc.rengu.igas.channel.alipay.core.model.ChnlBizResponse;
import cc.rengu.igas.channel.alipay.core.service.base.MchntService;
import cc.rengu.igas.channel.alipay.facade.request.AliQueryMerchantRequest;
import cc.rengu.igas.channel.alipay.facade.response.AliQueryMerchantResponse;
import cc.rengu.jradp.schedule.Schedule;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.CertInfoMapper;
import cc.rengu.oltp.service.common.dao.SecPlanInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.CertInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SecPlanInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayOpenAgentOrderQueryRequest;
import com.alipay.api.response.AlipayOpenAgentOrderQueryResponse;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 查询商户
 */
public class QueryMerchantService extends MchntService {

    @Override
    protected Object beforeBizProcess() throws Exception {
        AliQueryMerchantRequest aliQueryMerchantRequest = new AliQueryMerchantRequest();
        ConvertUtil.convertOutput(aliQueryMerchantRequest);
        return aliQueryMerchantRequest;
    }

    @Override
    protected ChnlBizResponse callBizService(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        int iReturnCode;
        AliQueryMerchantResponse aliQueryMerchantResponse = new AliQueryMerchantResponse();
        AliQueryMerchantRequest aliQueryMerchantRequest = (AliQueryMerchantRequest) request;
        DstChannelCfg dstChannelCfg = (DstChannelCfg) xmlTreeUtil.getXmlTreeObjectValue(AlipayTreeNodeConstant.DST_CHANNEL_CFG, DstChannelCfg.class);
        DstChannelInfo dstChannelInfo = (DstChannelInfo) xmlTreeUtil.getXmlTreeObjectValue(AlipayTreeNodeConstant.DST_CHANNEL_INFO, DstChannelInfo.class);

        ConvertUtil.convertInput(aliQueryMerchantRequest);
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, aliQueryMerchantRequest.getHeader().getTxnNum());
        /* 根据通道标识调用不同通道进行支付 */
        Schedule schedule = new Schedule();
        if (ChannelEnum.ALIP.getChannelType().equals(aliQueryMerchantRequest.getChannelId())) {
            return directQueryMchnt(aliQueryMerchantRequest, dstChannelCfg);
        } else if (ChannelEnum.NUAL.getChannelType().equals(aliQueryMerchantRequest.getChannelId()) ||
                ChannelEnum.UPAL.getChannelType().equals(aliQueryMerchantRequest.getChannelId())) {
            xmlTreeUtil.setXmlTreeStringValue(AlipayTreeNodeConstant.ALI_METHOD, "ant.merchant.expand.indirect.query");
            xmlTreeUtil.setXmlTreeStringValue(AlipayTreeNodeConstant.ALIPAY_APPID, dstChannelCfg.getAppId());
            xmlTreeUtil.setXmlTreeStringValue(AlipayTreeNodeConstant.ALIPAY_ORGPID, dstChannelCfg.getProviderMchntNo());
            iReturnCode = schedule.callService(dstChannelInfo.getDstServiceName(), 0);
        } else {
            rglog.error("不支持的通道选择，channelId:<{}>", aliQueryMerchantRequest.getChannelId());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }

        if (xmlTreeUtil.isExist(AlipayTreeNodeConstant.DEFINE_HTTP_URL_NODE)) {
            xmlTreeUtil.deleteXmlTreeNode(AlipayTreeNodeConstant.DEFINE_HTTP_URL_NODE);
        }
        if (0 != iReturnCode && 98 != iReturnCode) {
            rglog.error("调用支付宝服务失败，iReturnCode:<{}>", iReturnCode);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        } else if (98 == iReturnCode) {
            rglog.error("调用支付宝服务超时，iReturnCode:<{}>", iReturnCode);
            throw new BizException(RespCodeEnum.TIME_OUT_ERROR.getRespCode(), RespCodeEnum.TIME_OUT_ERROR.getRespDesc());
        }
        ConvertUtil.convertOutput(aliQueryMerchantResponse);
        String code = xmlTreeUtil.getXmlTreeStringValue(AlipayTreeNodeConstant.ALI_RET_CODE);
        String msg = xmlTreeUtil.getXmlTreeStringValue(AlipayTreeNodeConstant.ALI_RET_MSG);
        String subCode = xmlTreeUtil.getXmlTreeStringValue(AlipayTreeNodeConstant.ALI_RET_SUBCODE);
        String subMsg = xmlTreeUtil.getXmlTreeStringValue(AlipayTreeNodeConstant.ALI_RET_SUBMSG);
        if (!AlipayParamConstant.AILPAY_SUCCESS_CODE.equals(code)) {
            rglog.error("调用第三方服务失败,respCode=[{}],respDesc=[{}]", code, msg);
            aliQueryMerchantResponse.setRespCode((null == subCode) ? code : subCode);
            aliQueryMerchantResponse.setRespDesc((null == subMsg) ? msg : subMsg);
        } else {
            aliQueryMerchantResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            aliQueryMerchantResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        }
        ChnlBizResponse chnlBizResponse = new ChnlBizResponse();
        chnlBizResponse.setResult(aliQueryMerchantResponse);
        return chnlBizResponse;
    }

    @Override
    protected void afterBizProcess(ChnlBizResponse response) throws Exception {
        AliQueryMerchantResponse aliQueryMerchantResponse = (AliQueryMerchantResponse) response.getResult();
        ConvertUtil.convertInput(aliQueryMerchantResponse);
    }


    ChnlBizResponse directQueryMchnt(AliQueryMerchantRequest aliQueryMerchantRequest, DstChannelCfg dstChannelCfg) throws Exception {
        AliQueryMerchantResponse aliQueryMerchantResponse = new AliQueryMerchantResponse();
        ChnlBizResponse chnlBizResponse = new ChnlBizResponse();
        String instId = aliQueryMerchantRequest.getHeader().getInstId();

        /* 获取支付宝通讯配置参数 */
        SysParamService sysParamService = new SysParamServiceImpl();
        /*获取请求url*/
        SysParam sysParam = sysParamService.getSysParamInfo(instId, AlipayConfigConstant.ALIPAY_CONF_NODE, AlipayConfigConstant.ALIPAY_PAY_NET_URL);
        if (null == sysParam || StringUtil.isEmptyOrNull(sysParam.getParamValue())) {
            rglog.error("未配置支付宝直连专线URL地址，请配置");
            throw new BizException(RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespCode(), RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespDesc());
        }
        String requestUrl = sysParam.getParamValue();
        /*互联网代理IP*/
        sysParam = sysParamService.getSysParamInfo(instId, AlipayConfigConstant.ALIPAY_CONF_NODE, AlipayConfigConstant.ALIPAY_PROXY_NET_IP);
        String proxyIp = (null == sysParam || StringUtil.isEmptyOrNull(sysParam.getParamValue())) ? null : sysParam.getParamValue().trim();
        /*互联网代理端口*/
        sysParam = sysParamService.getSysParamInfo(instId, AlipayConfigConstant.ALIPAY_CONF_NODE, AlipayConfigConstant.ALIPAY_PROXY_NET_PORT);
        String proxyPort = (null == sysParam || StringUtil.isEmptyOrNull(sysParam.getParamValue())) ? null : sysParam.getParamValue().trim();
        /*报文类型*/
        sysParam = sysParamService.getSysParamInfo(instId, AlipayConfigConstant.ALIPAY_CONF_NODE, AlipayConfigConstant.ALIPAY_MSG_TYPE);
        String msgType = (null == sysParam || StringUtil.isEmptyOrNull(sysParam.getParamValue())) ? "json" : sysParam.getParamValue().trim();
        /*字符集*/
        sysParam = sysParamService.getSysParamInfo(instId, AlipayConfigConstant.ALIPAY_CONF_NODE, AlipayConfigConstant.ALIPAY_CHARSET);
        String charset = (null == sysParam || StringUtil.isEmptyOrNull(sysParam.getParamValue())) ? "UTF-8" : sysParam.getParamValue().trim();
        /*签名验签方式*/
        sysParam = sysParamService.getSysParamInfo(instId, AlipayConfigConstant.ALIPAY_CONF_NODE, AlipayConfigConstant.ALIPAY_SIGN_TYPE);
        String signType = (null == sysParam || StringUtil.isEmptyOrNull(sysParam.getParamValue())) ? "RSA2" : sysParam.getParamValue().trim();

        /* 根据通道安全计划获取安全计划 */
        String priKey = null;
        String pubKey = null;
        SecPlanInfoMapper secPlanInfoMapper = new SecPlanInfoMapperImpl();
        CertInfoMapper certInfoMapper = new CertInfoMapperImpl();
        List<SecPlanInfo> secPlanInfoList = secPlanInfoMapper.selectSecPlanInfoBySecPlanId(instId, dstChannelCfg.getSecPlanId());

        /* 获取签名验签证书（私钥） */
        Optional<SecPlanInfo> secPlanInfoOptSign = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(AlipayParamConstant.SIGN_CERT_TYPE)).findFirst();
        if (secPlanInfoOptSign.isPresent()) {
            CertInfo certInfoPri = certInfoMapper.selectCertInfoByPrimaryKey(instId + secPlanInfoOptSign.get().getSecPlanId() + secPlanInfoOptSign.get().getSecPlanType());
            if (certInfoPri != null) {
                priKey = certInfoPri.getCertValue();
            }
        }

        /* 获取签名验签证书（公钥） */
        Optional<SecPlanInfo> secPlanInfoOpt = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(AlipayParamConstant.VERIFY_CERT_TYPE)).findFirst();
        if (secPlanInfoOpt.isPresent()) {
            CertInfo certInfoPub = certInfoMapper.selectCertInfoByPrimaryKey(instId + secPlanInfoOpt.get().getSecPlanId() + secPlanInfoOpt.get().getSecPlanType());
            if (certInfoPub != null) {
                pubKey = certInfoPub.getCertValue();
            }
        }

        /* 调用支付宝开启代商户签约、创建应用事务 */
        rglog.debug("aliPayUrl = <{}>;appId = <{}>;priKey = <{}>;msgType = <{}>,charset = <{}>,pubKey = <{}>,signType = <{}>,proxyIp = <{}>,proxyPort = <{}>",
                requestUrl, dstChannelCfg.getAppId(), priKey, msgType, charset, pubKey, signType, proxyIp, proxyPort);
        AlipayClient alipayClient;
        if (StringUtil.isEmptyOrNull(proxyIp) || StringUtil.isEmptyOrNull(proxyPort)) {
            alipayClient = new DefaultAlipayClient(requestUrl, dstChannelCfg.getAppId(), priKey, msgType, charset, pubKey, signType);
        } else {
            alipayClient = new DefaultAlipayClient(requestUrl, dstChannelCfg.getAppId(), priKey, msgType, charset, pubKey, signType, proxyIp, proxyPort);
        }

        /* 查询代签约的结果 */
        rglog.debug("查询事务编号:{}", aliQueryMerchantRequest.getBatchNo());
        AlipayOpenAgentOrderQueryRequest alipayOpenAgentOrderQueryRequest = new AlipayOpenAgentOrderQueryRequest();
        Map<String, String> queryParamMap = new HashMap<>();
        queryParamMap.put("batch_no", aliQueryMerchantRequest.getBatchNo());
        alipayOpenAgentOrderQueryRequest.setBizContent(JSON.toJSONString(queryParamMap));
        rglog.debug("查询请求：{}", JSON.toJSONString(alipayOpenAgentOrderQueryRequest));
        AlipayOpenAgentOrderQueryResponse alipayOpenAgentOrderQueryResponse = alipayClient.execute(alipayOpenAgentOrderQueryRequest);
        rglog.debug("查询结果：{}", JSON.toJSONString(alipayOpenAgentOrderQueryResponse));
        if (alipayOpenAgentOrderQueryResponse.isSuccess()) {
            aliQueryMerchantResponse.setAliMchntNo(alipayOpenAgentOrderQueryResponse.getMerchantPid());
            if ("MERCHANT_CONFIRM_SUCCESS".equals(alipayOpenAgentOrderQueryResponse.getOrderStatus())) {
                aliQueryMerchantResponse.setAliMchntNo(alipayOpenAgentOrderQueryResponse.getMerchantPid());
                aliQueryMerchantResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
                aliQueryMerchantResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            } else {
                aliQueryMerchantResponse.setRespCode(alipayOpenAgentOrderQueryResponse.getCode());
                aliQueryMerchantResponse.setRespDesc(alipayOpenAgentOrderQueryResponse.getRejectReason());
                rglog.info("支付宝商户入驻申请单状态：{}", alipayOpenAgentOrderQueryResponse.getOrderStatus());
                rglog.error("受限信息:{}", alipayOpenAgentOrderQueryResponse.getRejectReason());
            }
        } else {
            aliQueryMerchantResponse.setRespCode((null == alipayOpenAgentOrderQueryResponse.getSubCode()) ? alipayOpenAgentOrderQueryResponse.getCode() : alipayOpenAgentOrderQueryResponse.getSubCode());
            aliQueryMerchantResponse.setRespDesc((null == alipayOpenAgentOrderQueryResponse.getSubMsg()) ? alipayOpenAgentOrderQueryResponse.getMsg() : alipayOpenAgentOrderQueryResponse.getSubMsg());
        }
        chnlBizResponse.setResult(aliQueryMerchantResponse);
        return chnlBizResponse;
    }
}
